package com.tduck.cloud.form.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.*;
import cn.hutool.http.HttpUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.tduck.cloud.common.constant.CommonConstants;
import com.tduck.cloud.common.entity.BaseEntity;
import com.tduck.cloud.common.util.*;
import com.tduck.cloud.form.entity.UserFormDataEntity;
import com.tduck.cloud.form.entity.UserFormItemEntity;
import com.tduck.cloud.form.entity.enums.FormItemTypeEnum;
import com.tduck.cloud.form.entity.struct.UploadResultStruct;
import com.tduck.cloud.form.mapper.UserFormDataMapper;
import com.tduck.cloud.form.request.QueryFormResultRequest;
import com.tduck.cloud.form.service.UserFormDataService;
import com.tduck.cloud.form.service.UserFormItemService;
import com.tduck.cloud.form.util.JsonContainsUtils;
import com.tduck.cloud.form.util.ListPageUtils;
import com.tduck.cloud.form.vo.FormDataTableVO;
import com.tduck.cloud.storage.cloud.OssStorageFactory;
import com.tduck.cloud.storage.util.StorageUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static com.tduck.cloud.form.constant.FormConstants.FORM_RESULT_NUMBER;

/**
 * 表单表单项(FormResult)表服务实现类
 *
 * @author smalljop
 * @since 2020-11-23 14:09:22
 */
@Service
@RequiredArgsConstructor
public class UserFormDataServiceImpl extends ServiceImpl<UserFormDataMapper, UserFormDataEntity> implements UserFormDataService {

    private final UserFormItemService userFormItemService;
    private final CacheUtils cacheUtils;

    @Override
    public void saveFormResult(UserFormDataEntity entity) {
        String formKey = entity.getFormKey();
        entity.setSerialNumber(cacheUtils.incr(StrUtil.format(FORM_RESULT_NUMBER, formKey), CommonConstants.ConstantNumber.ONE));
        entity.setSubmitAddress(AddressUtils.getRealAddressByIP(entity.getSubmitRequestIp()));
        this.save(entity);
    }


    /**
     * 下载表单结果中的附件
     *
     * @param request
     * @return
     */
    @Override
    public Result downloadFormResultFile(QueryFormResultRequest request) {
        String uuid = IdUtil.simpleUUID();
        List<UserFormItemEntity> userFormItemEntityList = userFormItemService.list(Wrappers.<UserFormItemEntity>lambdaQuery().eq(UserFormItemEntity::getFormKey, request.getFormKey()).in(UserFormItemEntity::getType, Lists.newArrayList(FormItemTypeEnum.UPLOAD.toString(), FormItemTypeEnum.IMAGE_UPLOAD.toString())));
        //结果
        FormDataTableVO formDataTableVO = this.listFormDataTable(request);
        List<Map> rows = formDataTableVO.getRows();
        if (CollectionUtil.isEmpty(rows) || CollectionUtil.isEmpty(userFormItemEntityList)) {
            return Result.failed("暂无收集附件，无法下载");
        }
        ThreadUtil.execAsync(() -> {
            List<String> paths = new ArrayList<>();
            List<InputStream> ins = new ArrayList<>();
            try {
                rows.forEach(result -> {
                    int index = 0;
                    String id = MapUtil.getStr(result, "id");
                    userFormItemEntityList.forEach(item -> {
                        List<Object> uploadResults = MapUtil.get(result, item.getFormItemId(), List.class);
                        if (CollectionUtil.isNotEmpty(uploadResults)) {
                            uploadResults.forEach(uFile -> {
                                UploadResultStruct uploadResult = Convert.convert(UploadResultStruct.class, uFile);
                                if (StrUtil.isNotBlank(uploadResult.getUrl())) {
                                    paths.add(new StringBuffer().append(item.getId()).append(CharUtil.DASHED).append(uploadResult.getName()).toString());
                                    byte[] bytes = HttpUtil.downloadBytes(uploadResult.getUrl());
                                    ins.add(IoUtil.toStream(bytes));
                                }
                            });
                        }
                    });
                    AsyncProcessUtils.setProcess(uuid, ++index / rows.size() + 1);
                });
                // 压缩上传oss
                ByteArrayOutputStream zipOutputStream = new ByteArrayOutputStream();
                ZipUtil.zip(zipOutputStream, paths.toArray(new String[]{}), ins.toArray(new InputStream[]{}));
                String downloadUrl = OssStorageFactory.build().upload(zipOutputStream.toByteArray(), StorageUtils.generateFileName("download", ".zip"));
                AsyncProcessUtils.setProcess(uuid, downloadUrl);
            } catch (Exception e) {
                log.error("download file", e);
            }
        });
        return Result.success(uuid);
    }

    @Override
    public FormDataTableVO listFormDataTable(QueryFormResultRequest request) {
        List<UserFormDataEntity> dataEntityList = new ArrayList<>();
        Long total = 0L;

        // 查询全部
//        if (0 == request.getPageNum() || ObjectUtil.isNull(request.getPageNum())) {
//            dataEntityList = this.list(Wrappers.<UserFormDataEntity>lambdaQuery()
//                    .eq(ObjectUtil.isNotNull(request.getFormKey()), UserFormDataEntity::getFormKey, request.getFormKey())
//                    .eq(UserFormDataEntity::getDeleteFlag, false)
//                    .eq(ObjectUtil.isNotNull(request.getId()), UserFormDataEntity::getId, request.getId())
//                    .ge(ObjectUtil.isNotNull(request.getBeginDate()), UserFormDataEntity::getTime, request.getBeginDate())
//                    .lt(ObjectUtil.isNotNull(request.getEndDate()), UserFormDataEntity::getTime, request.getEndDate()));
//            total = Long.valueOf(dataEntityList.size());
//        } else {
        List<UserFormDataEntity> allFormResultList = this.list(Wrappers.<UserFormDataEntity>lambdaQuery()
                .eq(ObjectUtil.isNotNull(request.getFormKey()), UserFormDataEntity::getFormKey, request.getFormKey())
                .eq(UserFormDataEntity::getDeleteFlag, false)
                .isNotNull(UserFormDataEntity::getOriginalData)
                .eq(ObjectUtil.isNotNull(request.getId()), UserFormDataEntity::getId, request.getId())
                .ge(ObjectUtil.isNotNull(request.getBeginDate()), UserFormDataEntity::getTime, request.getBeginDate())
                .lt(ObjectUtil.isNotNull(request.getEndDate()), UserFormDataEntity::getTime, request.getEndDate()));
        List<UserFormDataEntity> result = new ArrayList<>();
        if (ObjectUtil.isNotEmpty(request.getOptions())) {
            String[] optionsList = request.getOptions().split(",");
            for (UserFormDataEntity userFormDataEntity : allFormResultList) {
                Map<String, Object> originalData = userFormDataEntity.getOriginalData();
                if (ObjectUtil.isNotNull(originalData)) {
                    // 新建标志位
                    boolean hasAllData = false;
                    for (String string : optionsList) {
//                        boolean hasData = false;
                        for (Object map : originalData.entrySet()) {
                            if (((Map.Entry) map).getValue() instanceof String) {
                                String json = (String) ((Map.Entry) map).getValue();
                                if (json.equals(string)) {
                                    hasAllData = true;
                                    break;
                                }
                            }
                        }
                        // 如果当前查询项未匹配上数据项，直接中断
//                        if (!hasData) {
//                            hasAllData = false;
//                            break;
//                        }
                    }
                    // 如果所有查询项都匹配上了数据项，则将该表单数据加入结果集合
                    if (hasAllData) {
                        result.add(userFormDataEntity);
                    }
                }
            }
        }
        List<UserFormDataEntity> jsonContainsAll = JsonContainsUtils.getJsonContainsAll(request.getQueryData(), ObjectUtil.isNotEmpty(request.getOptions()) ? result : allFormResultList);
        dataEntityList = ListPageUtils.page(jsonContainsAll, (int) request.getPageNum(), (int) request.getPageSize());
        total = Long.valueOf(jsonContainsAll.size());
//        }
        List<Map> list = dataEntityList.stream().map(item -> {
            Map<String, Object> originalData = item.getOriginalData();
            item.setOriginalData(null);
            originalData.put(BaseEntity.Fields.createTime, LocalDateTimeUtil.formatNormal(item.getCreateTime()));
            originalData.put(BaseEntity.Fields.updateTime, LocalDateTimeUtil.formatNormal(item.getUpdateTime()));
            Map<String, Object> formDataMap = BeanUtil.beanToMap(item);
            formDataMap.putAll(originalData);
            return formDataMap;
        }).collect(Collectors.toList());
        return new FormDataTableVO(list, total);
    }

    @Override
    public Boolean deleteByIds(List<String> dataIdList, String formKey) {
        baseMapper.deleteBatchIds(dataIdList);
        return null;
    }

    @Override
    public Boolean updateFormResult(UserFormDataEntity entity) {
        UserFormDataEntity dataEntity = this.getById(entity.getId());
        dataEntity.setOriginalData(entity.getOriginalData());
        boolean update = this.updateById(dataEntity);
        return update;
    }

    @Override
    public Boolean updateBatchFormResult(List<UserFormDataEntity> entity) {
//        UserFormDataEntity dataEntity = this.getById(entity.getId());
//        dataEntity.setOriginalData(entity.getOriginalData());
        boolean update = this.updateBatchById(entity);
        return update;
    }


    @Override
    public FormDataTableVO listFormDataTableStatistics(QueryFormResultRequest request) {
        List<UserFormDataEntity> dataEntityList = this.list(Wrappers.<UserFormDataEntity>lambdaQuery().eq(ObjectUtil.isNotNull(request.getFormKey()), UserFormDataEntity::getFormKey, request.getFormKey())
                .eq(UserFormDataEntity::getDeleteFlag, false)
                .like(ObjectUtil.isNotNull(request.getItemId()), UserFormDataEntity::getOriginalData, request.getItemId())
                .ge(ObjectUtil.isNotNull(request.getBeginDate()), UserFormDataEntity::getTime, request.getBeginDate())
                .lt(ObjectUtil.isNotNull(request.getEndDate()), UserFormDataEntity::getTime, request.getEndDate()));
        Long total = (long) dataEntityList.size();
        List<Map> list = dataEntityList.stream().map(item -> {
            Map<String, Object> originalData = item.getOriginalData();
            item.setOriginalData(null);
            originalData.put(BaseEntity.Fields.createTime, LocalDateTimeUtil.formatNormal(item.getCreateTime()));
            originalData.put(BaseEntity.Fields.updateTime, LocalDateTimeUtil.formatNormal(item.getUpdateTime()));
            Map<String, Object> formDataMap = BeanUtil.beanToMap(item);
            formDataMap.putAll(originalData);
            return formDataMap;
        }).collect(Collectors.toList());
        return new FormDataTableVO(list, total);
    }

    @Override
    public List<Map<String, Object>> formDataListByIds(QueryFormResultRequest request) {
        String[] split = request.getId().split(",");
        // 获取数据实体列表
        List<UserFormDataEntity> dataEntityList = this.list(Wrappers.<UserFormDataEntity>lambdaQuery()
                .eq(UserFormDataEntity::getDeleteFlag, false)
                .in(UserFormDataEntity::getId, split));

        // 需要统计的体征列表
        List<String> physicalData = Arrays.asList("身高", "体重", "BMI", "体温", "血压", "脉搏", "血氧", "心电", "腰围", "臀围", "血糖");

        // 查询所有用户表单项实体并存储在Map中以提高查询效率
        Map<String, List<UserFormItemEntity>> formItemMap = new HashMap<>();
        for (UserFormDataEntity dataEntity : dataEntityList) {
            String formKey = dataEntity.getFormKey();
            if (!formItemMap.containsKey(formKey)) {
                List<UserFormItemEntity> formItems = userFormItemService.listByFormKey(formKey);
                formItemMap.put(formKey, formItems);
            }
        }

        // 构建体征名称到数据列表的映射
        Map<String, List<Map<String, Object>>> resultMap = physicalData.stream()
                .collect(Collectors.toMap(
                        // 体征名称作为键
                        physical -> physical,
                        // 根据体征名称过滤并构建对应的数据列表
                        physical -> {
                            List<Map<String, Object>> physicalList = new ArrayList<>();
                            for (UserFormDataEntity userFormDataEntity : dataEntityList) {
                                LocalDateTime createTime = userFormDataEntity.getCreateTime();
                                List<UserFormItemEntity> userFormItemEntities = formItemMap.get(userFormDataEntity.getFormKey());
                                for (UserFormItemEntity userFormItemEntity : userFormItemEntities) {
                                    String formItemId = userFormItemEntity.getFormItemId();
                                    String desc = userFormItemEntity.getType().getDesc();
                                    String label = userFormItemEntity.getLabel();
                                    Map<String, Object> originalData = userFormDataEntity.getOriginalData();
                                    // 如果表单项类型为输入类型且标签包含当前体征，则将对应数据添加到列表中
                                    if (FormItemTypeEnum.INPUT.getDesc().equals(desc) && label.contains(physical)) {
                                        originalData.entrySet().stream()
                                                .filter(entry -> formItemId.equals(entry.getKey()))
                                                .forEach(entry -> {
                                                    Map<String, Object> objectMap = new HashMap<>();
                                                    String formattedCreateTime = createTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
                                                    objectMap.put("createDate", formattedCreateTime);
                                                    objectMap.put("value", entry.getValue());
                                                    physicalList.add(objectMap);
                                                });
                                    }
                                }
                            }
                            return physicalList;
                        },
                        // 合并重复键的值列表
                        (existingList, newList) -> {
                            existingList.addAll(newList);
                            return existingList;
                        }
                ));

        // 将映射转换为最终结果列表
        List<Map<String, Object>> resultList = resultMap.entrySet().stream()
                .map(entry -> {
                    Map<String, Object> map = new HashMap<>();
                    map.put("name", entry.getKey()); // 将键作为"name"字段
                    map.put("list", entry.getValue()); // 将值列表作为"list"字段
                    return map;
                })
                .collect(Collectors.toList());

        return resultList;
    }

}